classdef C_Tx < handle
    %C_TX Summary of this class goes here
    %   Detailed explanation goes here

    properties (GetAccess = {?C_OpticalChannel, ?C_Eval, ?C_Rx}, SetAccess='private')
        Param;
        M;
        GI_size;
        
        TxDataBin;
        TxDataDec;
        Symbols;
        Signal;
        Amplitude;
        
        sigSize
        TxDataSize;
        
        constellationObj;
    end
    
    methods
        function this = C_Tx()
            this.constellationObj = C_constellation.Instance();
        end
        
        function Initialise(this, param)
            this.Param = param;
            this.sigSize = [round(this.Param.numSubcarriers*2*(1+this.Param.GI_sizePct/100)) this.Param.numOfdmBlocks];
            this.M = this.constellationObj.getDataSize(this.constellationObj,this.Param.ActiveModType);
            this.TxDataSize = this.Param.numOfdmBlocks*length(this.Param.ActiveModBand)*log2(this.M);
            this.TxDataBin = zeros(1, this.TxDataSize);
            this.TxDataDec = zeros(1, this.TxDataSize / log2(this.M));
            this.Symbols = zeros(this.Param.numSubcarriers, this.Param.numOfdmBlocks) + 1i * zeros(this.Param.numSubcarriers, this.Param.numOfdmBlocks);
            this.GI_size = round((this.Param.GI_sizePct/100)*this.Param.numSubcarriers*2);
            this.Amplitude = this.Param.numSubcarriers*2/sqrt(length(this.Param.ActiveModBand));
        end
        
        function Generate(this)
                        
            if (this.TxDataSize ~= 0)
                GenRandData(this);
                this.TxDataDec = bi2de(reshape(this.TxDataBin', log2(this.M), [])', 'left-msb');           
                this.Symbols(this.Param.ActiveModBand',:) = reshape(this.constellationObj.GetSymbol(this.constellationObj, this.TxDataDec, this.Param.ActiveModType), length(this.Param.ActiveModBand), this.Param.numOfdmBlocks);
            end
            
            if (~isempty(this.Param.PilotModBand))
                this.Symbols(this.Param.PilotModBand',:) = repmat(this.constellationObj.GetSymbol(this.constellationObj, this.Param.PilotModData, this.Param.PilotModType).', 1, this.Param.numOfdmBlocks);
            end
            
            stage1Sig = [this.Symbols ; zeros(1,this.Param.numOfdmBlocks) ; conj(flipud(this.Symbols(2:end,:)))];                     
            stage2Sig = ifft(stage1Sig);                                                                                                              
            stage3Sig = addGI(stage2Sig, this.Param.GI_type, this.GI_size); 
            this.Signal = stage3Sig;           
        end
        
        function SigOut = GetTxSignal(this)
            SigOut = this.Signal;
        end
               
    end
    
end

function GenRandData(this)
    this.TxDataBin = randi([0 1],1,this.TxDataSize);  
end

function SigOut = AddPacketSeparation(this, SigIn)
%     SigOut = [SigIn zeros(1,this.Param.packetSeparationDuration * this.Param.Fs)];
end

function SigOut = addGI(SigIn, GI_type, GI_size)
    blockSize = size(SigIn, 1);
    
    switch GI_type
        case 'zeros'
            Padding = [eye(blockSize) ; zeros(GI_size,blockSize)];
        case 'cyclic prefix'
            Padding = [eye(blockSize) ; eye(GI_size,blockSize)];
    end
    
    SigOut = Padding * SigIn;
end








